import 'dart:async';
import 'dart:math';

import 'package:collection/collection.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_2b_client/apis/MarketOrderApi.dart';
import 'package:flutter_2b_client/model/IntIdAndName.dart';
import 'package:flutter_hooks/flutter_hooks.dart';

import 'FormItem.dart';

class GoodsListItem extends HookWidget {
  final Future<void> Function(int amount, int? unitId) onUpdateAmount;
  final bool edited;
  final String name;
  final String barcode;
  final int inStore;
  final int? amount;
  final String? boxSpecification;

  final List<QueryGoodsUnitResponse> units;
  final IntIdAndName? unit;

  const GoodsListItem(
      {Key? key,
      required this.onUpdateAmount,
      this.units = const [],
      this.unit,
      this.edited = true,
      required this.name,
      required this.barcode,
      required this.inStore,
      this.amount,
      this.boxSpecification})
      : super(key: key);

  @override
  Widget build(BuildContext context) {
    var focusNode = useFocusNode();
    var textEditingController = useTextEditingController();
    var currentAmountState = useState(amount ?? 0);
    useEffect(() {
      textEditingController.text = (currentAmountState.value).toString();

      return null;
    }, [currentAmountState.value]);


    var setNewAmountTimerState = useState<Timer?>(null);
    var updateAmountLoadingState = useState(false);

    var themeData = Theme.of(context);
    var basicUnit = useMemoized(
        () => units.firstWhereOrNull((element) => element.isBasicUnit),
        [units]);
    var currentUnitIdState =
        useState<int?>(unit?.id ?? basicUnit?.id ?? units.firstOrNull?.id);
    final currentUnit = useMemoized(
        () => units.firstWhereOrNull(
            (element) => element.id == currentUnitIdState.value),
        [units, currentUnitIdState.value]);

    var unitIsBasic = useMemoized(() {
      return currentUnit?.isBasicUnit == true;
    }, [currentUnit, unit]);
    updateAmountAndUnit(int amount, int? unitId) async {
      if (setNewAmountTimerState.value != null &&
          setNewAmountTimerState.value!.isActive) {
        setNewAmountTimerState.value!.cancel();
      }
      setNewAmountTimerState.value =
          Timer(const Duration(milliseconds: 300), () async {
        if (updateAmountLoadingState.value) return;
        final adjustedAmount = max(amount, 0);
        try {
          updateAmountLoadingState.value = true;
          await onUpdateAmount(adjustedAmount, currentUnitIdState.value);
        } finally {
          updateAmountLoadingState.value = false;
        }
      });
    }

    setNewAmount(int amount) async {
      currentAmountState.value = amount;
      await updateAmountAndUnit(amount, currentUnitIdState.value);
    }

    setNewUnit(int? unitId) async {
      currentUnitIdState.value = unitId;
      await updateAmountAndUnit(currentAmountState.value, unitId);
    }

    useEffect(() {
      focusNode.addListener(() {
        if (!focusNode.hasFocus) {
          var amount = int.tryParse(textEditingController.text);
          if(amount!=null){
            setNewAmount(amount);
          }
        }
      });
      return (){
        focusNode.dispose();
      };
    }, []);

    return Card(
      elevation: 2,
      child: Padding(
        padding: const EdgeInsets.all(8.0),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            Text(
              name,
              style: themeData.textTheme.titleSmall,
            ),
            Text(barcode, style: themeData.textTheme.labelMedium),
            Builder(builder: (context) {
              var basicUnitName = basicUnit?.name ?? "";
              var list = <Widget?>[
                FixedWidthKeyPair("库存", inStore.toString()),
                FixedWidthKeyPair.ofNullableValue(
                    "数量",
                    (max(
                                    1,
                                    !unitIsBasic &&
                                            units.isNotEmpty &&
                                            basicUnit != null &&
                                            currentUnit != null
                                        ? currentUnit.basicMultiple
                                        : 1) *
                                currentAmountState.value)
                            .toString() +
                        basicUnitName),
                FixedWidthKeyPair.ofNullableValue("箱规", boxSpecification),
              ].whereNotNull().toList();
              return DefaultTextStyle(
                style: DefaultTextStyle.of(context)
                    .style
                    .copyWith(color: themeData.hintColor),
                child: Row(
                  children: list,
                ),
              );
            }),
            if (edited)
              Align(
                alignment: Alignment.bottomRight,
                child: Row(
                  mainAxisSize: MainAxisSize.min,
                  children: [
                    InkWell(
                      onTap: updateAmountLoadingState.value ||
                              currentAmountState.value <= 1
                          ? null
                          : () {
                              setNewAmount((currentAmountState.value) - 1);
                            },
                      customBorder: const CircleBorder(),
                      child: Container(
                        width: 20,
                        height: 20,
                        decoration: const BoxDecoration(shape: BoxShape.circle),
                        child: const Icon(
                          Icons.remove,
                          size: 12,
                        ),
                      ),
                    ),
                    SizedBox(
                      width: 36,
                      height: 20,
                      child: TextField(
                        controller: textEditingController,
                        textAlign: TextAlign.center,
                        focusNode:focusNode,
                        keyboardType: TextInputType.number,
                        onTap: () {},
                        style: const TextStyle(fontSize: 12),
                        onSubmitted: (value) {
                          setNewAmount(int.tryParse(value) ?? 0);
                        },
                        textInputAction: TextInputAction.done,
                        inputFormatters: [
                          FilteringTextInputFormatter.digitsOnly
                        ],
                        // Only numbers,
                        readOnly: updateAmountLoadingState.value,
                      ),
                    ),
                    InkWell(
                      onTap: updateAmountLoadingState.value
                          ? null
                          : () {
                              setNewAmount((currentAmountState.value) + 1);
                            },
                      customBorder: const CircleBorder(),
                      child: Container(
                        width: 20,
                        height: 20,
                        decoration: const BoxDecoration(shape: BoxShape.circle),
                        child: const Icon(
                          Icons.add,
                          size: 12,
                        ),
                      ),
                    ),
                    if (units.isNotEmpty)
                      DropdownButton(
                        style: Theme.of(context).textTheme.labelMedium,
                        items: units
                            .map(
                              (e) => DropdownMenuItem<int>(
                                value: e.id,
                                child: Row(
                                  mainAxisAlignment:
                                      MainAxisAlignment.spaceBetween,
                                  children: [
                                    Text(e.name),
                                    e.isBasicUnit
                                        ? Container()
                                        : Text(e.basicMultiple.toString() +
                                            (basicUnit?.name ?? "")),
                                  ],
                                ),
                              ),
                            )
                            .toList(),
                        value: currentUnitIdState.value,
                        onChanged: (value) {
                          setNewUnit(value);
                        },
                        padding: const EdgeInsets.symmetric(horizontal: 8),
                      ),
                  ],
                ),
              ),
          ],
        ),
      ),
    );
  }
}

class FixedWidthKeyPair extends HookWidget {
  final String label;
  final String value;

  static Widget? ofNullableValue(String label, String? value) {
    return value == null ? null : FixedWidthKeyPair(label, value);
  }

  const FixedWidthKeyPair(this.label, this.value, {Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return SizedBox(
        width: 80,
        child: Text(
          "$label:$value",
          maxLines: 1,
          overflow: TextOverflow.ellipsis,
        ));
  }
}
